#include <iostream>
#include <nng/nng.h>
#include <nng/protocol/reqrep0/req.h>
#include <thread>
#include <vector>
#include <string>
#include <cstring>

const std::string SERVER_URL = "tcp://127.0.0.1:8888";
const std::string REQUEST_MSG = "This is a test request.";

// 线程函数，用于每个线程向服务器发送请求并接收响应
void client_thread() {
    nng_socket sock;
    int rv;

    // 创建请求套接字
    if ((rv = nng_req0_open(&sock)) != 0) {
        std::cerr << "nng_req0_open failed: " << nng_strerror(rv) << std::endl;
        return;
    }

    // 连接到服务器
    if ((rv = nng_dial(sock, SERVER_URL.c_str(), nullptr, 0)) != 0) {
        std::cerr << "nng_dial failed: " << nng_strerror(rv) << std::endl;
        nng_close(sock);
        return;
    }

    // 创建要发送的消息
    nng_msg *msg;
    if ((rv = nng_msg_alloc(&msg, REQUEST_MSG.length())) != 0) {
        std::cerr << "nng_msg_alloc failed: " << nng_strerror(rv) << std::endl;
        nng_close(sock);
        return;
    }
    memcpy(nng_msg_body(msg), REQUEST_MSG.c_str(), REQUEST_MSG.length());

    std::thread::id thread_id = std::this_thread::get_id();
    std::cout << "[t:"<< thread_id << "]client send request" << std::endl;

    // 发送消息
    if ((rv = nng_sendmsg(sock, msg, 0)) != 0) {
        std::cerr << "nng_sendmsg failed: " << nng_strerror(rv) << std::endl;
        nng_close(sock);
        return;
    }

    std::cout << "[t:"<< thread_id << "]client waiting for response" << std::endl;
    // 接收服务器响应
    nng_msg *recv_msg;
    if ((rv = nng_recvmsg(sock, &recv_msg, 0)) != 0) {
        std::cerr << "nng_recvmsg failed: " << nng_strerror(rv) << std::endl;
        nng_close(sock);
        return;
    }

    // 打印服务器响应
    std::string response(reinterpret_cast<char *>(nng_msg_body(recv_msg)), nng_msg_len(recv_msg));
    std::cout << "[t:"<< thread_id << "]client received response:" << response << std::endl;

    // 释放接收到的消息
    nng_msg_free(recv_msg);

    // 关闭套接字
    nng_close(sock);
}

int main() {
    std::vector<std::thread> threads;

    // 创建 10 个线程
    for (int i = 0; i < 100; ++i) {
        threads.emplace_back(client_thread);
    }

    // 等待所有线程完成
    for (auto& thread : threads) {
        thread.join();
    }

    return 0;
}